目录
模板方法
为什么使用模板方法
模板方法应用实例
模板方法
模板方法:在一个方法中定义一个算法的框架,然后将该方法中的一些步骤延迟到子类中,使得再不改变算法的前提下,重新定义自己的算法。
看了模板方法的定义,可能感觉这和策略模式没有什么区别,都是对算法的封装,但是其差别在那里呢?
区别:策略模式是通过组合的方式将多个类的方法组合在一起,而模板方法是通过继承来实现的,即为在父类中有一个final的不可修改的方法,将我们的算法逻辑写在里面,然后其组合起来的算法可以在其子类中具体的根据实际情况去定义。
为什么要用模板方法
现在我们要实现一个流水线,这个流水线上,我们可以生产过的机器,而这些机器组成上是存在一些差别的,如果机器的种类不是很多,我们可以针对每一个机器都做一条流水线,但是如果机器种类很多,如果这些机器的出货时间是不同的,那么一旦第一批货出完,那么该机器的生产流水线就会闲置下来,利用率就会很低,以此类比,如果我们针对每种机型创建一个类,势必会使得我们的代码很臃肿,会有很多的重复代码存在,根据设计模式的基本原则,将不变的抽离出来,对变化的部分进行封装,通过这来使我们的代码更简洁的同时减少后期的维护成本。
因此我们可以这么写
//机器装配的基类
public abstract class Machine{
//机器装配的流程,final不可被复写,保证方装配算法不被破坏
final void produce(){
createFrame();
addHead();
addBody();
if(ifDressup())
dressUp();
}
//创建框架
public abstract void createFrame();
//添加一个机器头
public abstract void addHead();
//添加一个机器的身子
public abstract void addBody();
//为机器进行装扮
public abstract void dressUp();
//判断是否为该机器进行装扮
public boolean ifDressup(){
return true;
}
}
//继承自基类的一个子类
public class InflatableDoll{
public void createFrame(){
System.out.println("This is a Frame");
}
public void addBody(){
System.out.println("This is a body");
}
public void dressUp(){
System.out.println("This is a beautiful cloth");
}
}
上述有注释的地方就不在此啰嗦了,上一篇结尾的时候要说下的一个钩子方法,这里提一下,这里的豆子方法就是ifDressup(),如果没有钩子方法,我们的的装配算法逻辑在父类中是final的,我们是不可以对其进行控制的,因此也就丧失了灵活性,当然我们希望能够在子类中对其进行控制,这样我们就可以更灵活的控制这个装配过程,因此出现了钩子方法,通过钩子方法将我们的子类和父类挂接起来,在我们的模板方法中将钩子方法作为一个装配条件,然后在我们的子类中根据我们自己的要求来覆写这个方法。、
模板方法应用实例
现实中,有那些例子呢?看到着,应该能够想起来一些什么,我们开发中的view,大多都是通过这种方式来进行的。以Android中的view为例子
public class View{
/**
* 钩子操作,空实现
*/
protected void onDraw(Canvas canvas) {
}
/**
*钩子操作,空实现
*/
protected void dispatchDraw(Canvas canvas) {
}
//算法骨架
public void draw(Canvas canvas) {
if (!verticalEdges && !horizontalEdges) {
// 步骤1
if (!dirtyOpaque) onDraw(canvas);
// 步骤2
dispatchDraw(canvas);
// 步骤3
onDrawScrollBars(canvas);
return;
}
}
//... ...
}
View类
public class MyView extends View {
public MyView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
}
}
通过上面的例子,我们可以看出我们的view控件绘制的一个流程。
下篇更新工厂模式,这个是当时看的时候最迷糊的一个了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。